![]() |
Программирование для Internet |
||
|
На предыдущем занятии мы рассмотрели некоторые управляющие структуры языка JavaScript. Сейчас мы, отчасти, продолжим это разговор и рассмотрим встроенные в язык объекты, функции, и, снова забегая вперед, внешний объект Form.
Понятие объекта является одним из самых важных в JavaScript (наверное, не сильно преувеличим, если скажем "в современном программировании"). Практически все, с чем мы имеем дело в данном языке, кроме чисел - объекты. К ним относятся строки, функции, и т.п. Кроме того, все элементы HTML документа, такие как формы, элементы форм, изображения, гиперссылки и т.п. - все это, с точки зрения JavaScript - объекты.
Объектом в JavaScript (как и в программировании вообще) называется каким-либо образом определенный набор данных и процедур их обработки, которые рассматриваются как единое целое. Это очень важно, что данные и процедуры их обработки являются одним целым. Именно этим и характеризуются объекты. Именно таким образом мы прячем всю обработку данных внутри определения объекта.
Пока все это несколько туманно, но попробуем рассмотреть пример. На прошлом занятии мы познакомились с объектами типа Date. Как устроен объект Date внутри нам во-первых неизвестно, а во-вторых, в достаточной мере безразлично. Может быть, там хранится одно единственное число - количество миллисекунд с нуля часов 01.01.1970, а может быть, там хранится отдельно число, месяц, год и т.д. Мы этого не знаем, да и не имеем нужды знать. Все, что мы знаем, это то, что кроме данных, с объектом связаны еще и процедуры их обработки. Вот, с помощью этих-то процедур мы и получаем доступ к объекту.
Например, если мы хотим изменить значение года в объекте Date, мы пишем нечто вроде.
var a = new Date(); a.setYear(2000);
Нам не нужно знать, хранится ли там "год" обособленно или нет. Пусть об этом болит голова у функции setYear().
Представим теперь, что мы храним даты в виде записей языка Pascal или структур языка C. В этом случае мы обязаны знать внутреннюю организацию записи. Допустим, если мы знаем, что год там хранится в виде отдельного поля, то рассмотренный пример мог бы быть записан, например, так:
a.year = 2000;
Казалось бы, хрен редьки не слаще. Во втором случае мы обязаны знать, что год хранится отдельным полем, зато в первом - мы обязаны знать о существовании функции setYear(). Однако, разница есть и мы ее почувствуем как только разработчики браузера захотят поменять внутреннее представление дат (например, для решения проблемы трехтысячного года или еще для чего-нибудь). Тогда, в первом случае это никак не отразится на нашей программе (будем надеяться, что они заодно поменяют и реализацию setYear(), чтобы она, по прежнему, правильно устанавливала год). Во втором же случае, мы будем вынуждены вносить изменения во все наши программы, т.к. поля year в новой реализации может не оказаться вовсе.
Таким образом Pascal'евские записи описывают только структуру данных, а всю обработку оставляют программисту. Объекты же включают в себя как структуру данных, так и процедуры их обработки. Более того, хорошие объекты "прячут" от программиста свои данные и предоставляют ему доступ к ним только через встроенные процедуры обработки. Таким образом разработчик объекта может свободно изменять внутреннюю структуру данных, никак не задевая программистов, которые пользуются его объектами.
Это можно сравнить с радиоприемником. Если бы разработчики следовали идеологии записей, они бы спаяли схему и сказали бы пользователю: "если хочешь изменить громкость - замени вон тот резистор". Даже если бы Вы к этому привыкли, как только Вы купите новый приемник, Вам придется узнавать какой резистор нужно заменять в нем и "перепривыкать". При обектном же подходе, на панель выведена рукоятка и Вы знаете, что громкость можно изменять, не заботясь о том, какие там внутри резисторы и есть ли они там вообще.
Такое объединение в одно целое данных и программ их обработки называется инкапсуляцией. Внутренние данные объекта называются свойствами (может быть не самый удачный перевод английского properties). Инкапсулированные же процедуры обработки называются методами.
Повторюсь, что обычно, при инкапсуляции, разработчик скрывает от пользователя внутреннюю структуру данных, оставляя лишь доступ к ним через методы. Это позволяет разработчику во-первых иметь свободу изменять внутреннюю реализацию объекта, никак не влияя на программы пользователей, а во-вторых дает ему полный контроль над своим объектом и гарантирует целостность данных. Например, при записе-орентированной реализации мы могли бы написать нечто вроде:
a.date = 32;
и запись была бы испорчена. При объектном же подходе, если мы напишем
a.setDate(32);
то программа setDate() сама проверит корректность параметра и примет необходимые меры. Конечно, мы могли бы проверять все и вручную, но удобнее, когда эти глупые проверки от нас спрятаны - инкапсулированы.
Наконец,
объект это объединенная в одно целое (инкапсулированная) структура данных и процедуры (методы) обработки этих данных.
Однако, объект это только "описание того как все должно быть". Чтобы иметь возможность работать, нам нужно уметь создавать экземпляры объектов (instances). Для этого служит оператор new. Его синтаксис прост. За ключевым словом new должно следовать имя объекта и список параметров для его инициализации в скобках. Если параметры не нужны, все равно нужно писать скобки, опускать их нельзя. Например:
a = new Date(); // a содержит экземпляр // объекта Date соответсвующий // текущей дате и времени b = new Date(1998,0,1); // b содержит экземпляр // объекта Date соответсвующий // первому января 1998 года
Коль скоро и a и b являются экземпляром одного и того же объекта Date - процедуры обрабоотки у них одни и те же. Разница лишь в том, какие значения записаны во внутренних данных.
Образно можно сказать, что два экземпляра одного и того же объекта отличаются друг от друга в точности как два одинаковых радиоприемника. Последние могут быть настроены на разные станции. Любой из них можно перенастроить на другую станцию и это никак не повлияет на другой. Однако, это не мешает им быть абсолютно одинаковыми по внутреннему устройству.
Всегда ли необходимо создавать экземпляр объекта для работы с данными? Вообще говоря - да. Возвращаясь к аналогии с радиоприемником, можно сказать, что выключенный радиоприемник (вернее, неограниченное количество таковых) задает объект. Когда же мы включаем его и настраиваем на определенную станцию - мы создаем экземпляр этого объекта. Мы можем включить еще один и настроить на другую (можно и на ту же) станцию - создан еще один экземпляр. Таким образом, мы можем реально воспользоваться объектом только создав его экземпляр(ы). (Разумеется можно воспользоваться выключенным приемником для забивания гвоздей, но мы изучаем программирование, а не психиатрию.)
Объект document, с которым мы уже имели дело (не создавая его, кстати) просто создан за нас системой, незадолго до запуска нашей программы.
Существуют еще и так-называемые статические объекты, экземпляры которых создавать тоже не нужно (Math, например), потому, что они обладают свойствами как объекта так и экземпляра, но, о них позже.
Для того, чтобы обратиться к свойству или методу объекта, нужно написать имя этого свойства (метода) через точку от имени переменной-экземпляра. В таких случаях говорят, что мы обращаемся к методу (свойству) в контексте конкретного экземпляра. В случае метода, за именем должен следовать список параметров в скобках. Скобки, как почти везде в этом языке, нельзя опускать. Например:
a = new Date(1998,0,1); b = new Date(1999,0,1); document.write(a.getYear()); // Обратились к методу getYear() // в контексте экземпляра a, // будет напечатано 1998 document.write(b.getYear()); // Обратились к методу getYear() // в контексте экземпляра b, // будет напечатано 1999
Замечание о терминологии: во многих языках программирования принята другая терминология. То, что мы называем "объектом", часто называется "классом", а то, что мы называем "экземпляром" - называют "объектом" или "экземпляром класса". Сути понятий это не меняет. Постарайтесь не путаться и всегда понимать о чем идет речь.
На следующей лекции мы будем подробно говорить об объектах, их устройстве, их замечательном умении наследовать свойства и методы друг от друга и т.д. Кроме того, мы научимся создавать собственные объекты. Сегодня же мы обсудим несколько объектов, которые встроены в язык и которыми мы всегда можем пользоваться в своих программах.
Объект Array служит для организации массивов.
Массивы, как и строки, могут быть и константами. Константные массивы записываются перечислением элементов в квадратных скобках. Например:
var a = [1,2,3,4,5,6,7,8,9,0]; // a получает, в качестве значения, массив
Чтобы обратиться к элементу массива, достаточно, после имени переменной-массива (или непосредственно после константы-массива) записать индекс в квадратных скобках.
Массивы всегда индексируются с нуля.
Теперь мы можем написать программу, которая по русски печатает день недели, гораздо короче, чем мы писали раньше:
var day_names = ["воскресенье","понедельник","вторник","среда", "четверг","п\ятница","суббота"]; var today = new Date(); document.write(day_names[today.getDay()]);
или, еще короче:
var today = new Date(); document.write(["воскресенье","понедельник","вторник","среда", "четверг","п\ятница","суббота"][today.getDay()]);
или, совсем коротко:
document.write(["воскресенье","понедельник","вторник","среда", "четверг","п\ятница","суббота"][(new Date()).getDay()]);
Когда мы записываем константный массив, мы неявно создаем экземпляр объекта Array. Посмотрим теперь как создавать его явно.
Это можно сделать различными способами. Самый простой:
var myArray = new Array();
создается экземпляр обекта Array (попросту, массив) нулевой длины.
Другой способ:
var myArray = new Array(6);
создается массив myArray длиною в 6 элементов. Этим способом нужно пользоваться осторожно. Если Вы в тэге <SCRIPT> укажете LANGUAGE="JavaScript", то все будет в порядке. Если же Вы укажете LANGUAGE="JavaScript1.2", то в MSIE и в NN 3.0 все будет, по прежнему, нормально, но вот в NN 4.0 вы получите массив из одного элемента, который равен шести.
Можно, также задать массив и сразу же перечислить его элементы:
var myArray = new Array("one","two","three");
здесь создается массив из трех элементов. Не рекомендуется применять этот способ для создания массива состоящего из одного элемента, т.к. при этом вознникает неоднозначность.
var a = new Array("five"); // нет проблем var a = new Array(5); // будет создан массив // или из 5 элементов // или из одного. // см. выше.
Длина массивов в JavaScript может изменяться во время работы программы. Как только программа обращается к элементу массива выходящему за текущую длину, массив удлиняется на необходимую величину.
var a = new Array(); // длина = 0 a[0] = "hello"; // длина = 1 a[2] = "hi"; // длина = 3 a[100] = "Howdy"; // длина = 101 // (с a[0] по a[100])
Массивы, это довольно новая вещь в HTML. Как мы скоро увидим, многие методы этого объекта работают пока только в Netscape Navigator и не работают в MSIE. На самом деле, еще в MSIE 3.0 массивов не было вовсе. Как же быть, если ими хочется пользоваться, и, при этом, не хочется игнорировать этот, сравнительно не старый, браузер. Ответ прост. Можно определить "самодельный" объект подобный Array. Созданием своих объектов мы займемся на следующем занятии. Тогда мы и вернемся к этому вопросу.
Как уже говорилось, массивы ялвяются объектами и, значит, имеют свойства и методы. Всего у объекта Array четыре свойста, но нас сегодня интересует одно - length. Свойство length равно текущей длине массива. Вернемся к предыдущему примеру и добавим печать этого свойства.
var a = new Array(); // длина = 0 document.write(a.length+" "); a[0] = "hello"; // длина = 1 document.write(a.length+" "); a[2] = "hi"; // длина = 3 document.write(a.length+" "); a[100] = "Howdy"; // длина = 101 document.write(a.length);
Будет напечатано:
0 1 3 101
Методы объекта Array коротко описаны в таблице. Все они работают в Netscape. К сожалению, в MSIE многие не реализованы. В третьем столбце таблицы проставлены галочки напротив тех методов, которые работают-таки и там и там.
Обратите внимание на метод toString(). Этот метод присутствует во всех объектах встроенных в язык. Очень полезно определять его и в своих собственных объектах. Он отвечает за то, как данный объект будет преобразовываться к строковому типу (например, при печати). Более того, это имя зарезервировано. Всякий раз, когда системе нужно предстваить объект в виде строки, она пытается вызвать метод toString() данного объекта. Таким образом,
var a = new Array("one","two"); // Печать document.write(a); // Абсолютно тоже самое document.write(a.toString());
Все остальные методы (кроме toString()) достаточно подробно описаны на отдельной страничке. Там же имеются примеры на каждый метод.
Как нетрудно догадаться, объект String служит для представления строк. Мы уже имели дело со строковыми константами, знаем как их записывать и конкатенировать. Пришла пора познакомиться со строками поближе.
Для того чтобы создать экземпляр объекта String можно просто присвоить переменной строковую константу, а можно воспользоваться операцией new. Разница между этими способами настолько тонкая, что мы будем считать их идентичными. Примеры:
var a = "Это строка"; var b = new String("Еще строка"); var c = new String(b); var d = new String(a+b+c);
Здесь, строка с получает начальное значение "Еще строка", а строка d - "Это строкаЕще строкаЕще строка".
Как и в случае с массивами, единственное свойтво объекта String, которое нас будет реально интересовать, это length - текущая длина.
Что касается методов, то таковых у объекта String много - аж 29 штук, но мы рассмотрим только часть. Те, кого интересуют все методы, могут ознакомиться с ними по фирменной документации компании Netscape Communications, которая (к сожалению, на английском языке) имеется на учебном сервере. К счастью, все описанные здесь методы благополучно работают как в NN, так и в MSIE.
Метод | Описание |
charAt | Возвращает символ стоящий в указанной позиции в строке. |
fontcolor | Добавляет к строке тэг так, чтобы при печати она печаталась указанным цветом. |
indexOf | Возвращает идекс первого вхождения указанной подстроки в строку. |
lastIndexOf | Возвращает идекс последнего вхождения указанной подстроки в строку. |
slice | Выделяет подстроку из строки. |
split | Резделяет строку на подстроки в соответсвие с указанным разделителем. |
substr | Выделяет подстроку из строки. |
substring | Выделяет подстроку из строки. |
toLowerCase | Возвращает строку, преобразованную к нижнему регистру. |
toUpperCase | Возвращает строку, преобразованную к верхнему регистру. |
Объект String, пожалуй единственный из порядочных объектов, который не имеет метода toString() :-)
Ознакомьтесь, пожалуйста, с перечисленными в таблице методами поближе. Там же Вы найдете и примеры на каждый метод.
Во всех, приличных языках программирования есть функции. Они здорово помогают сократить и упростить для чтения запись программы. Есть они и JavaScript. Правда здесь они играют не только (и даже не столько) свою обычную утилитарную роль. К счастью, другое (и основное) назначение функций - тема отдельной лекции. Поэтому, сейчас мы ограничимся рассмотрением функций как таковых, к которым мы привыкли по другим языкам прогаммирования.
Итак, чтобы определить функцию, записываем ключевое слово function, за ним (через пробел) имя нашей функции и, в скобках, список параметров. Если параметров нет, скобки все рано должны присутствовать. И, наконец, в фигурных скобках, собственно тело функции, т.е. операторы, которые она должна исполнять. Опять же, если она ничего не должна делать, все равно нужны фигурные скобки, хотя бы пустые. Если функция должна возвращать значение, то оно возвращается с помощью ключевого слова return. Записывается return, а за ним выражение, которое и будет результатом. Кстати, оператор return вызывает немедленное прекращение выполнения функции и выход из нее.
function doNothing () {} function alwaysTrue () { return true; } function sum (a,b) { return a+b; } function nod(n,m) { return (m) ? nod(m,n%m) : n; }
Обращаться к функции можно по имени. Если она возвращает значение, то его можно использовать в выражениях. Если у функции нет параметров, пара скобок все равно обязательна. Вот, собственно и все. Рекурсия допустима.
Несколько слов о параметрах. Во-первых, при обращении к функции их можно опускать. Однако, делать это нужно "с конца". Нельзя, например, указать второй параметр, не указав первого. Функция может "узнать" передали ей параметр или нет, сравнив есго со значением null. Например:
function f(a) { if (a==null) document.write("Missing parameter a<BR>"); else document.write("Parameter a="+a+"<BR>"); } f(2,1); f(1); f();
Будет напечатано:
Parameter a=2 Parameter a=1 Missing parameter a
В последних версиях браузеров появился специальный массив arguments. С его помощью функция может просмотреть все свои аргументы и, таким образом, иметь переменное количество аргументов. Например, мы хотим составить списки героев популярных сказок. Программа может выглядеть так:
function print_list() { document.write("<OL>"); for (var i = 0; i < print_list.arguments.length; i++) document.write("<LI>"+print_list.arguments[i]+"</LI>"); document.write("</OL>"); } document.write("<STRONG>Трое из Простоквашино</STRONG><BR>"); f("Матроскин","Д\яд\я Федор","Шарик"); document.write("<P><STRONG>Репка</STRONG><BR>"); f("Дедка","Бабка","Внучка","Жучка","Кошка","Мышка");
Будет напечатано:
Трое из Простоквашино
Репка
Обратите внимание, как мы обращаемся к массиву arguments. Имя функции, точка, arguments. Неправда-ли, похоже, что функция - это экземпляр объекта, а массив arguments - его свойство? :-)
Есть несколько функций встроенных в язык, которые могут оказаться полезными. Мы рассмотрим четыре такие функции.
Функция eval принимает один аргумент - строку и, рассматривая ее как JavaScript программу, выполняет ее. Результатом eval, будет результат, получившийся при выполнении программы. Например:
document.write(eval("2*2")+"<BR>"); document.write(eval("2+2*2")+"<BR>"); document.write(eval("var i=0;while (i<10) i++; i;"));
Будет напечатано:
4 6 10
Обе эти функции принимают один аргумент - строку и пытаются преобразовать ее соответственно к целому или вещественному числу. Если это удалось, то они возвращают полученное число, если не удалось, возвращается NaN. NaN (Not a Number) - специальное значение, которое, потом, можно проверить (см. след. функцию).
У функции parseInt может быть еще один аргумент - число обозначающее систему счисления.
Обе функции разбирают строку символ за символом. Разбор считается успешным, если первым символом (не считая пробелов и табуляций) оказалась цифра. Например:
document.write(parseInt("22")+"<BR>"); document.write(parseInt(" 22")+"<BR>"); document.write(parseInt(" 22руб.")+"<BR>"); document.write(parseInt("цена 22руб.")+"<BR>"); document.write(parseFloat("22.12")+"<BR>"); document.write(parseFloat("22,12"));
Будет напечатано:
22 22 22 NaN 22.12 22
Заметьте, что строка " 22руб." благополучно преобразоваллась в число 22.
Позволяет сравнить значение, возвращенное parseInt и parseFloat с NaN. Возвращает истину если равно, и ложь, если не равно. Применим ее в предыдущем примере.
document.write(isNaN(parseInt("22"))+"<BR>"); document.write(isNaN(parseInt(" 22"))+"<BR>"); document.write(isNaN(parseInt(" 22руб."))+"<BR>"); document.write(isNaN(parseInt("цена 22руб."))+"<BR>"); document.write(isNaN(parseFloat("22.12"))+"<BR>"); document.write(isNaN(parseFloat("22,12")));
Будет напечатано:
false false false true false false
Теперь, когда мы уже изучили функции, попробуем написать программу, которая выводит строку текста с плавно меняющимся цветом.
// Перевод чисел в шестнадцатиричную систему // нужен, чтобы сформировать триплет цвета #rrggbb // function to_hex(n) { var res=""; for(var i=0; i<6; i++) { var s = "0123456789ABCDEF".substr(n%16,1)+res; res = s; n = Math.floor(n/16); } return "#"+res; } // Эта функция формирует триплет цвета #rrggbb // function rgb(r,g,b) { return to_hex(Math.round(b)+Math.round(g)*256+Math.round(r)*65536); } // Эта функция устанавливает цвет каждой буквы // так, чтобы он плавно переходил от буквы к букве // затем, она печатает текст. function Colorchange(r1,g1,b1,r2,g2,b2,stroka){ var len = stroka.length; var y1=(r2-r1)/len; var y2=(g2-g1)/len; var y3=(b2-b1)/len; for (var i=0; i<len; i++,r1+=y1,g1+=y2,b1+=y3) document.write(stroka.substr(i,1).fontcolor(rgb(r1,g1,b1))); }
При обращении к этой функции нужно указать семь параметров: r, g, b первой буквы, r, g, b последней буквы и строку для вывода. Например, если мы напишем:
Colorchange(255,120,0,140,0,255, "Никогда не думай, что ты иная, чем могла бы быть, иначе "+ "как будучи иной в тех случаях, когда иною нельзя не быть.");
То получим нечто вроде:
Сегодня мы рассмотрели так много всего интересного, что нам просто необходима какая-нибудь возможность не только печатать информацию в документ, но и вводить ее от пользователя.
Попробуем воспользоваться для этого формами. Дело в том, что как только Вы написали тэг <FORM>, Вы, возможно, не зная об этом, создали экземпляр объекта Form! Этот экземпляр, в свою очередь, является свойством "полузнакомого" нам объекта document. Обращаться к форме проще всего по имени (позже, мы научимся делать это и по другому!).
В свою очередь, каждый элемент формы (поле ввода, например) является свойством объекта Form и к нему, тоже можно обращаться по имени.
Наконец, у поля ввода есть свойтсто value, которое есть ничто иное, как обыкновенная строка. Мы можем читать ее значение и присваивать ей новое!
И последнее, на второй лекции я обещал рассказать об обработчиках событий. Про один из них можно поговорить уже сейчас. Любую кнопку можно нажать. Другими словами, можно иницировать событие click. Чтобы включить обработчик события, достаточно, в соответствующем тэге, написать ON<имя события>=..., например, ONCLICK="нечто". Вместо "нечто" можно писать любой текст на JavaScript. Там могут быть простые команды, обращения к функциям и т.д. Вот этот самый текст и является обработчиком события!
Это надо немедленно попробовать. Пишем:
<FORM NAME="myform1"> <INPUT NAME="dspl" TYPE="text" SIZE=40><BR> <INPUT TYPE="button" VALUE="Click Me" ONCLICK="document.myform1.dspl.value='Hello, world';"> <INPUT TYPE="reset"> </FORM>
Смотрите, в ответ на нажатие кнопки, мы присваиваем свойтству value поля dspl значение "Hello, world". Кнопка же reset все стирает, работа у нее такая. Попробуем?
Давайте сделаем, хотя бы, небольшую обработку. Пусть наша форма понимает слова "Hello" и "Hi". На них она будет отвечать ":-)", а на все остальное - ":-(". Поехали:
<SCRIPT LANGUAGE="JavaScript"> <!-- function check_input() { var s = document.myform2.dspl.value.toLowerCase(); if ((s=="hello") || (s == "hi")) document.myform2.dspl.value = ":-)"; else document.myform2.dspl.value = ":-("; } //--> </SCRIPT> <FORM NAME="myform2"> <INPUT NAME="dspl" TYPE="text" SIZE=40><BR> <INPUT TYPE="button" VALUE="Click Me" ONCLICK="check_input();"> <INPUT TYPE="reset"> </FORM>
Обратите внимание на команду:
var s = document.myform2.dspl.value.toLowerCase();
я, заодно, преобразовал содержимое поля к нижнему регистру, чтобы можно было легко узнавать слова написанные как "hello", "Hello", или, даже, "hElLo".
Ну, как? Работет?
Ну, хорошо, с полями ввода понятно, а как быть с многострочными полями? Оказвается также! У них тоже есть value. Кстати, и с кнопками также, чем они хуже-то? Давайте сделаем кнопку, которая считает сколько раз на нее нажали.
<SCRIPT LANGUAGE="JavaScript"> <!-- var cnt = 0; function count() { document.myform3.btn.value = "Нажата "+(++cnt)+" раз"; } //--> </SCRIPT> <FORM NAME="myform3"> <INPUT NAME=btn TYPE=button VALUE="Нажата 0 раз" ONCLICK="count();"> </FORM>
Простите, я поленился подгонять окончание слова "раз". Заметьте, что описание переменной cnt я расположил вне функции. Это очень важно. Если бы она была внутри функции, она получала бы значение 0 при каждом входе.
Ну, хватит, хорошего помаленьку. Обрабатывать чек-боксы, радио-кнопки и т.д. научимся в другой раз. Рассмотрим примера.
Сейчас мы напишем очень простенький калькулятор, который, тем не менее, умеет делать массу вещей - тригонометрические функции, скобки и даже циклы и функции! Мы, конечно, помним, что все это умеет делать функция eval, но те, кто не помнит, пусть удивляются!
<SCRIPT LANGUAGE="JavaScript"> <!-- function calc() { document.myform4.exp.value = eval(document.myform4.exp.value); } //--> </SCRIPT> <FORM NAME="myform4"> Чего посчитать: <INPUT NAME="exp" TYPE="text" SIZE=50><P> <INPUT TYPE="button" VALUE=" Вперед " ONCLICK="calc();"> </FORM>
И всего делов. Правда, здесь нигде не проверяется правильность введенного выражения, старайтесь не ошибаться :-)
Попробуйте подсунуть ему 2*2. А, если 123*(12/(21-7)*5+2)-1.5 ? Если еще не надоело, попробуйте подсунуть ему такое:
function nod(n,m){return (m)?nod(m,n%m):n;}nod(55,121);
В ответ он выдаст вам наибольший общий делитель чисел 55 и 121. Вот такой калькулятор получился.
Напоследок, попробуйте разобраться сами в другом калькуляторе. Сначала, попрбуйте сделать такой же самостоятельно. Если уж совсем ничего не получится, возьмите текст через view-source и разберитесь.
Главная страница | Замечания? Комментарии? Идеи? |